/*
 * Copyright (c) 2025 Industrial Software Feature Database
 */
package com.comac.ins.isfd.service.impl.section;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.comac.ins.common.core.exception.base.BaseException;
import com.comac.ins.common.core.utils.StringUtils;
import com.comac.ins.common.mybatis.core.page.PageQuery;
import com.comac.ins.common.mybatis.core.page.TableDataInfo;
import com.comac.ins.isfd.constant.enums.IsfdSectionTypeEnum;
import com.comac.ins.isfd.domain.IsfdSection;
import com.comac.ins.isfd.domain.IsfdSectionResult;
import com.comac.ins.isfd.domain.bo.IsfdSectionBo;
import com.comac.ins.isfd.domain.bo.query.IsfdSectionQueryBo;
import com.comac.ins.isfd.domain.vo.IsfdSectionCountResultObjectVo;
import com.comac.ins.isfd.domain.vo.IsfdSectionVo;
import com.comac.ins.isfd.mapper.IsfdSectionMapper;
import com.comac.ins.isfd.mapper.IsfdSectionResultMapper;
import com.comac.ins.isfd.service.IIsfdLayupEquivalentMaterialService;
import com.comac.ins.isfd.service.IIsfdSectionService;
import com.comac.ins.isfd.util.CommonUtils;
import com.comac.ins.isfd.util.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 型材库抽象类层
 *
 * @author hxloongs
 * @date 2024-7-30
 */
@Slf4j
public abstract class IsfdAbstractSectionService implements IIsfdSectionService {
    @Autowired
    protected IsfdSectionMapper isfdSectionMapper;
    @Autowired
    protected IsfdSectionResultMapper isfdSectionResultMapper;
    @Autowired
    protected IIsfdLayupEquivalentMaterialService iIsfdLayupEquivalentMaterialService;

    @Override
    public abstract String generateSerialNumber(IsfdSectionBo bo);

    /**
     * 获取attributeNumber
     */
    protected String geAttributeNumber(String preAttributeNumber) {
        List<IsfdSectionVo> isfdSectionVos = isfdSectionMapper.queryRightLikeByAttributeNumber(preAttributeNumber);
        String attributeNumber = null;
        // 如果不存在记录，直接生成
        // 如果存在记录，取最近的一条自增
        if (org.springframework.util.CollectionUtils.isEmpty(isfdSectionVos)) {
            attributeNumber = CommonUtils.padToEightDigits(preAttributeNumber);
        } else {
            IsfdSectionVo isfdSectionVo = isfdSectionVos.get(0);
            String oldAttributeNumber = isfdSectionVo.getAttributeNumber();
            attributeNumber = CommonUtils.numberIncrementOne(oldAttributeNumber);
        }
        return attributeNumber;
    }

//    @Override
//    public Boolean checkUnique(IsfdSectionBo isfdSectionBo, String hashUniqueKey) {
//        Boolean isUpdate = Boolean.FALSE;
//        Long id = isfdSectionBo.getId();
//        if (id == null) {
//            IsfdSection oldIsfdSection = isfdSectionMapper.selectOne(new LambdaQueryWrapper<IsfdSection>()
//                .eq(IsfdSection::getHashUniqueKey, hashUniqueKey));
//            if (oldIsfdSection != null) {
//                throw new BaseException("当前算法类型下，已经存在相同入参和对应的计算结果，不可重复计算，请确认入参后重试！");
//            }
//        } else {
//            IsfdSection oldIsfdSection = isfdSectionMapper.selectById(id);
//            if (oldIsfdSection == null) {
//                throw new BaseException("修改失败，数据不存在，请确认id后重试！");
//            }
//            String hashUniqueKeyForDb = oldIsfdSection.getHashUniqueKey();
//            if (hashUniqueKey.equals(hashUniqueKeyForDb)) {
//                throw new BaseException("当前算法类型下，已经存在相同入参和对应的计算结果，不可重复计算，请确认入参后重试！");
//            }
//            isUpdate = Boolean.TRUE;
//        }
//        return isUpdate;
//    }

    /**
     * 当前无需校验幂等，修改与20250905的需求改动
     * 相同参数，型材编号重新生成
     */
    @Override
    public Boolean checkUnique(IsfdSectionBo isfdSectionBo, String hashUniqueKey) {
        Boolean isUpdate = Boolean.FALSE;
        Long id = isfdSectionBo.getId();
        if (id != null) {
            IsfdSection oldIsfdSection = isfdSectionMapper.selectById(id);
            if (oldIsfdSection == null) {
                throw new BaseException("修改失败，数据不存在，请确认id后重试！");
            }
            isUpdate = Boolean.TRUE;
        }
        return isUpdate;
    }

    @Override
    public TableDataInfo<IsfdSectionVo> queryPage(IsfdSectionQueryBo bo) {
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageNum(bo.getPageNum());
        pageQuery.setPageSize(bo.getPageSize());
        Wrapper<IsfdSection> wrapper = buildQueryWrapper(bo);
        Page<IsfdSectionVo> result = isfdSectionMapper.queryPageList(pageQuery.build(), wrapper);
        return TableDataInfo.build(result);
    }

    @Transactional
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids) {
        for (Long id : ids) {
            isfdSectionMapper.deleteById(id);
            isfdSectionResultMapper.delete(new LambdaQueryWrapper<IsfdSectionResult>()
                .eq(IsfdSectionResult::getSecId, id));
        }
        return Boolean.TRUE;
    }


    @Override
    public List<IsfdSectionCountResultObjectVo> listCountByListByField(String field) {
        List<IsfdSectionCountResultObjectVo> sectionCountResultList = new ArrayList<>();
        QueryWrapper queryWrapper = new QueryWrapper<>();
        queryWrapper.select(field, "COUNT(*) as total_count");
        queryWrapper.groupBy(field);

        List<Map<String, Object>> list = isfdSectionMapper.selectMaps(queryWrapper);
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(m -> {
                sectionCountResultList.add(new IsfdSectionCountResultObjectVo(null, (String) m.get(field), (Long) m.get("total_count")));
            });
        }
        return sectionCountResultList;
    }

    @Override
    public List<IsfdSectionCountResultObjectVo> listTimeCount(String field, Date startTime, Date endTime) {
        List<IsfdSectionCountResultObjectVo> result = new ArrayList<>();
        QueryWrapper queryWrapper = new QueryWrapper<>();

        // 判断 field 是否为空，如果为空则不按该字段分组
        if (StringUtils.isEmpty(field)) {
            queryWrapper.select("DATE_FORMAT(create_time, '%Y-%m') as month", "COUNT(*) as total_count");
            queryWrapper.groupBy("month");
        } else {
            queryWrapper.select("DATE_FORMAT(create_time, '%Y-%m') as month", field + " as field_value", "COUNT(*) as total_count");
            queryWrapper.groupBy("month", "field_value");
        }

        // 时间条件
        if (Objects.nonNull(startTime) && Objects.nonNull(endTime)) {
            queryWrapper.between("create_time", startTime, endTime);
        } else if (Objects.nonNull(startTime)) {
            queryWrapper.ge("create_time", startTime);
        } else if (Objects.nonNull(endTime)) {
            queryWrapper.le("create_time", endTime);
        }

        List<Map<String, Object>> list = isfdSectionMapper.selectMaps(queryWrapper);

        // 获取指定时间范围内的所有月份
        List<String> allMonths = DateUtils.getAllMonthsBetween(startTime, endTime);
        Set<String> fieldValues = list.stream()
            .filter(m -> m.get("field_value") != null)
            .map(m -> (String) m.get("field_value"))
            .collect(Collectors.toSet());

        // 如果没有指定 field，只用月份显示
        if (StringUtils.isEmpty(field)) {
            allMonths.forEach(month -> {
                Long count = list.stream()
                    .filter(m -> month.equals(m.get("month")))
                    .map(m -> (Long) m.get("total_count"))
                    .findFirst()
                    .orElse(0L);
                result.add(new IsfdSectionCountResultObjectVo(month, "", count));
            });
        } else {
            // 对每个月和每个字段值进行组合，确保没有数据的组合也显示 totalCount=0
            for (String month : allMonths) {
                for (String fieldValue : fieldValues) {
                    Long count = list.stream()
                        .filter(m -> month.equals(m.get("month")) && fieldValue.equals(m.get("field_value")))
                        .map(m -> (Long) m.get("total_count"))
                        .findFirst()
                        .orElse(0L);
                    result.add(new IsfdSectionCountResultObjectVo(month, fieldValue, count));
                }
            }
        }
        return result;
    }


    /**
     * 交给各个实现类实现
     * <p>
     * 该方法需要实现的业务逻辑包含如下：
     * 1.截取对应字符串、并校验
     * 2.幂等生成和校验
     * 3.计算
     * 4.保存落表
     */
    public abstract Boolean save(IsfdSectionBo isfdSectionBo);

    protected Wrapper<IsfdSection> buildQueryWrapper(IsfdSectionQueryBo bo) {
        QueryWrapper<IsfdSection> lqw = Wrappers.query();
        lqw.eq(StringUtils.isNotBlank(bo.getType()) && !IsfdSectionTypeEnum.ALL.getValue().equals(bo.getType()), "s.type", bo.getType())
            .likeRight(StringUtils.isNotBlank(bo.getSerialNumber()), "s.serial_number", bo.getSerialNumber())
            .eq(StringUtils.isNotBlank(bo.getAttributeNumber()), "s.attribute_number", bo.getAttributeNumber())
            .eq(StringUtils.isNotBlank(bo.getMat1Id()), "s.MAT1_ID", bo.getMat1Id())
            .eq(StringUtils.isNotBlank(bo.getTLayerCode()), "s.tL_layer_code", bo.getTLayerCode())
            .in(CollectionUtil.isNotEmpty(bo.getMetadataManagementIds()), "s.metadata_management_id", bo.getMetadataManagementIds())
            .orderByDesc("s.create_time");
        return lqw;
    }

}
